package cn.ztuo.bitrade.dao;

import cn.ztuo.bitrade.entity.*;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.querydsl.QueryDslPredicateExecutor;
import org.springframework.data.repository.query.Param;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;

public interface ContractOrderMapper extends JpaRepository<ContractOrder, String>, JpaSpecificationExecutor<ContractOrder>, QueryDslPredicateExecutor<ContractOrder> {

    List<ContractOrder> findByPositionFlagNotAndStatusInAndMemberId(ContractEnumType.ContractOrderPositionFlag positionFlag, List<Integer> status, Long memberId);
    /**
     * 查询已提交订单的所有合约
     * @param symbol 合约代号
     * @return
     */
    @Query("select c from  ContractOrder c where c.symbol =?1 ORDER BY c.listTime desc ")
    List<ContractOrder> findBySymbol(String symbol);
    ContractOrder findByOrderId(String orderId);
    List<ContractOrder> findByDirectionAndStatusOrderByPriceAsc(ContractOrderDirection sell, ContractOrderStatus nodeal);
    List<ContractOrder> findAllByMemberIdAndSymbol(Long memberId, String symbol);
    List<ContractOrder> findAllByMemberId(Long memberId);
    List<ContractOrder> findAllByStatusAndSymbol(ContractOrderStatus status, String symbol);
    List<ContractOrder> findAllByStatus(ContractOrderStatus status);

    //--------------------------------------------------------------------------------------------------------------------


    @Modifying
    @Query("update ContractOrder contract set contract.tradedAmount = contract.tradedAmount + ?1  where contract.orderId = ?2")
    int increaseTradeAmount(BigDecimal amount, String orderId);

    @Modifying
    @Query("update ContractOrder  contract set contract.status = :status where contract.orderId = :orderId")
    int updateStatus(@Param("orderId") String orderId, @Param("status") ContractOrderStatus status);

    @Query(value="select coin_symbol unit,FROM_UNIXTIME(completed_time/1000, '%Y-%m-%d'),sum(traded_amount) amount, sum(nowp) nowp from contract_order where FROM_UNIXTIME(completed_time/1000, '%Y-%m-%d') = :date and direction = 1 and status = 2 group by unit",nativeQuery = true)
    List<Object[]> getContractTurnoverCoin(@Param("date") String date);

    @Query(value="select base_symbol unit,FROM_UNIXTIME(completed_time/1000, '%Y-%m-%d'),sum(turnover) amount, sum(nowp) nowp from contract_order where FROM_UNIXTIME(completed_time/1000, '%Y-%m-%d') = :date and direction = 1 and status = 2 group by unit",nativeQuery = true)
    List<Object[]> getContractTurnoverBase(@Param("date") String date);

    @Query(value="select base_symbol , coin_symbol,FROM_UNIXTIME(completed_time/1000, '%Y-%m-%d'),sum(traded_amount),sum(turnover),sum(nowp) from contract_order where FROM_UNIXTIME(completed_time/1000, '%Y-%m-%d') = :date and direction = 1 and status = 2 group by base_symbol,coin_symbol",nativeQuery = true)
    List<Object[]> getContractTurnoverSymbol(@Param("date") String date) ;

    @Query(value="select coin_symbol unit,FROM_UNIXTIME(completed_time/1000, '%Y-%m-%d') date,sum(traded_amount) amount , sum(nowp) nowp from contract_order where direction = 1 and status = 2 group by unit,date",nativeQuery = true)
    List<Object[]> getContractTurnoverCoin();

    @Query(value="select base_symbol unit,FROM_UNIXTIME(completed_time/1000, '%Y-%m-%d') date,sum(turnover) amount, sum(nowp) nowp from contract_order where  direction = 1 and status = 2 group by unit,date",nativeQuery = true)
    List<Object[]> getContractTurnoverBase();

    @Query(value="select base_symbol , coin_symbol,FROM_UNIXTIME(completed_time/1000, '%Y-%m-%d') date,sum(traded_amount),sum(turnover),sum(nowp) from contract_order where  direction = 1 and status = 2 group by base_symbol,coin_symbol,date",nativeQuery = true)
    List<Object[]> getContractTurnoverSymbol() ;

    /**
     * 查询该用户近30天的交易量
     * @param memberId
     * @return
     */
    @Query("SELECT count(a.orderId) FROM ContractOrder a WHERE  a.memberId = :memberId AND a.completedTime BETWEEN :beginDate AND :endDate")
    int countContractOrderByMemberId(@Param("memberId") Long memberId, @Param("beginDate") Long beginDate, @Param("endDate") Long endDate);
//    List<ContractOrder> findAllByMemberIdAndMarginTradeAndStatus(Long memberId, BooleanEnum marginTrade, ContractOrderStatus status);

    @Query(value = "select o.memberId,count(o.memberId) as c from ContractOrder o where o.listTime between :startTime and :endTime GROUP BY o.memberId")
    List<Object[]> countOrdersByMemberIdAndCreateTime(@Param("startTime") Long startTime, @Param("endTime") Long endTime);


    @Query(value = "select contract from ContractOrder contract where contract.listTime< :cancleTime and contract.status=0 and contract.orderResource=0")
    List<ContractOrder> queryContractOrderByTimeById(@Param("cancleTime") long cancelTime);

    @Transactional
    @Modifying
    @Query(value = "update contract_order set status=1 where order_id=:orderId and status=5",nativeQuery = true)
    int pushWaitingOrderByOrderId(@Param("orderId") String orderId);

    @Modifying
    @Query(value = "select contract from ContractOrder contract where contract.memberId = :memberId and contract.positionType = :positionType and (contract.status = 1 or (contract.status = 5 and (contract.type=2)) )")
    List<ContractOrder> findNeedCancelOrders(@Param("memberId") Long memberId, @Param("positionType") ContractOrderPositionType positionType);

    List<ContractOrder> findAllBySymbolAndStatus(String symbol, ContractOrderStatus waitingTrigger);
}
